import Vue from "vue";
import Router from "vue-router";
import store from "../store";
import Util from "../utils/util";
import Auth from "./auth";

// 获取子路由文件信息
const corpFiles = require.context("@/pages/corp", true, /\.vue$/);
const projectFiles = require.context("@/pages/project", true, /\.vue$/);

const originalPush = Router.prototype.push;
Router.prototype.push = function push(location, onResolve, onReject) {
  if (onResolve || onReject) {
    return originalPush.call(this, location, onResolve, onReject);
  }
  return originalPush.call(this, location).catch(err => err);
};

/**
 * 设置子路由
 * @param pathPre {String} 子路由前缀
 * @param files 文件信息
 */
const setRoutes = (pathPre, files) => {
  try {
    const result = [];
    files.keys().forEach(key => {
      const [, path] = key.match(/\.(\/[\w|\-|\/]+).vue$/);
      if (!path && path === "index") return;
      const name = path.replace(/(\/\w{1})+/g, item => {
        return item ? item.replace("/", "").toUpperCase() : "";
      });
      result.push({
        path,
        name: `${pathPre}${name}`,
        meta: {
          hasProject: pathPre === "project"
        },
        component: resolve => {
          require([`@/pages/${pathPre}${path}`], resolve);
        }
      });
    });
    return result;
  } catch (e) {
    // eslint-disable-next-line
    console.error("setRoutes error");
  }
  return [];
};

// 基础路由
const baseRoutes = [
  {
    path: "/login",
    name: "login",
    meta: {
      hasProject: false
    },
    component: resolve => {
      require(["@/pages/login"], resolve);
    }
  },
  {
    path: "/",
    component: resolve => {
      require(["@/pages/default"], resolve);
    },
    redirect: "/index",
    meta: {
      hasProject: false
    },
    children: [
      {
        path: "index",
        alias: "/",
        meta: {
          hasProject: false
        },
        component: resolve => {
          require(["@/pages/corp/index"], resolve);
        }
      }
    ]
  },
  {
    path: "*",
    component: resolve => {
      require(["@/pages/404"], resolve);
    }
  }
];

// 权限路由
const authRoutes = [
  {
    path: "/",
    component: resolve => {
      require(["@/pages/default"], resolve);
    },
    redirect: "/index",
    meta: {
      hasProject: false
    },
    children: [
      {
        path: "index",
        alias: "/",
        meta: {
          hasProject: false
        },
        component: resolve => {
          require(["@/pages/corp/index"], resolve);
        }
      },
      ...setRoutes("corp", corpFiles)
    ]
  },
  {
    path: "/project",
    component: resolve => {
      require(["@/pages/index"], resolve);
    },
    redirect: "/project/index",
    meta: {
      hasProject: true
    },
    children: [
      {
        path: "/project/index",
        alias: "/project",
        meta: {
          hasProject: true
        },
        component: resolve => {
          require(["@/pages/project/index"], resolve);
        }
      },
      ...setRoutes("project", projectFiles)
    ]
  }
];

Vue.use(Router);

const createRouter = (config = {}) => {
  return new Router({
    // base: '',
    mode: "hash",
    scrollBehavior: () => ({
      y: 0
    }),
    routes: [...baseRoutes],
    ...config
  });
};

const router = createRouter();

/**
 * 设置路由信息
 * @param data {Object} route
 */
const setInfo = data => {
  if (!data) return {};
  const result = {};
  Object.keys(data).forEach(key => {
    if (key !== "matched") result[key] = data[key];
  });
  return result;
};

/**
 * 从cookie获取登录信息
 * @return data: 登录信息，hasLogin: 是否登录
 */
const loginValidate = () => {
  let data = {};
  try {
    const userInfo = Util.getLocalStorage("user_info");
    data = JSON.parse(userInfo);
  } catch (e) {}
  const keys = Object.keys(data);
  const userList = ["userId", "uuid"];
  // 校验是否登录
  const hasLogin = userList.every(key => keys.includes(key));
  return {
    data,
    hasLogin
  };
};

// 重置状态
const resetAuth = () => {
  store.commit("updateHasRole", false);
  store.commit("updateHasToProject", false);
};

/**
 * 更新项目相关信息、设置权限和路由
 */
const setProjectInfo = async (to, from) => {
  const { matched, path } = to;
  if (from.path === to.path) return;
  // 是否在项目模块
  const hasProject = matched.some(item => item.path === "/project");
  if (!hasProject && !(from.path === "/" && path === "/project")) {
    const fromPathvalidater =
      from.path === "/project" || from.matched.some(v => v.path === "/project");
    const toPathvalidater = matched.some(item => !/^\//.test(item.path));
    if (fromPathvalidater && toPathvalidater && store.state.currentProjectId) {
      store.commit("updateCurrentProjectId", "");
      resetAuth();
    }
    return;
  }
  const projectId = Util.getLocalStorage("projectId");
  // 重置项目权限
  const hasResetAuth = from.path === "/" && !store.state.hasToProject;
  if (!projectId) {
    await store.dispatch("getProjectListByUser");
    hasResetAuth && resetAuth();
    return;
  }
  store.commit("updateCurrentProjectId", projectId);
  hasResetAuth && resetAuth();
  const projectInfo = store.state.currentProjectInfo;
  if (projectInfo && Object.keys(projectInfo).length) return;
  await store.dispatch("getProjectListByUser");
};

/**
 * 路由全局前置守卫
 * @param to 即将要进入的目标 路由对象
 * @param from 当前导航正要离开的路由
 * @param next {Function} 路由执行函数
 */
router.beforeEach(async function(to, from, next) {
  const { hasLogin, data } = loginValidate();
  // 不需要登录的页面
  const routeList = ["/login", "/404"];
  const notRequired = routeList.includes(to.path);
  store.commit("updateLoginStatus", hasLogin);
  // 更新用户信息
  store.commit("updateUserInfo", data);
  store.commit("updateRouteToInfo", setInfo(to));
  // 未登录情况
  if (!hasLogin) {
    if (!notRequired) {
      next("/login");
      return;
    }
    next();
    return;
  } else if (notRequired) {
    next();
    return;
  }
  await setProjectInfo(to, from);
  if (store.state.hasRole || store.state.hasToProject) return next();
  console.log("-----------------login-----------------");
  resetRouter();
  const { success, authMenu } = await store.dispatch("getMenuList");
  if (!success) return next(false);
  if (process.env.NODE_ENV !== "production") {
    authRoutes.forEach(item => {
      router.addRoute(item);
    });
    next({ ...to, replace: true });
    return;
  }
  const result = Auth.filterRoute(authRoutes, authMenu);
  result &&
    result.length &&
    result.forEach(item => {
      router.addRoute(item);
    });
  next({ ...to, replace: true });
});

router.afterEach((to, from) => {
  store.commit("updateRouteFromInfo", setInfo(from));
});

// 重置路由
export function resetRouter() {
  const newRouter = createRouter();
  router.matcher = newRouter.matcher;
}

export default router;
